package com.zoweunion.mechanic.util.gaode;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.zoweunion.mechanic.util.MapApiEnum;
import com.zoweunion.mechanic.util.MapKey;
import com.zoweunion.mechanic.util.constants.Constants;
import com.zoweunion.mechanic.util.MyException;
import jodd.http.HttpRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 高德地址解析工具
 *
 * @Auth zhangjun
 */
@Component
public class AddressGEOUtil {

    @Autowired
    RestTemplate restTemplate;

    public static final int SERVICE_ID = 140494;//轨迹服务id;name=trace


    /**
     * 查询行政区
     *
     * @return
     */
    public JSONArray selectDistrict(String keywords) throws MyException {

        // 调用高德地图 将地址转换为经纬度province
        String gaodeJson = restTemplate.getForObject(
                "https://restapi.amap.com/v3/config/district?key=e4dff7935045e4aadf06e230816b9fcc&subdistrict=1&extensions=base&keywords="
                        + keywords, String.class);

        //判断是否查询失败
        if (JSONObject.parseObject(gaodeJson).getString("status").equals("0")) {
            throw new MyException(Constants.CODE_HANDEL_FAILED, "业务操作失败");
        }

        JSONArray jsonArray = JSONArray.parseObject(gaodeJson).getJSONArray("districts");

        if (jsonArray.size() == 0) {
            throw new MyException(Constants.CODE_HANDEL_FAILED, "业务操作失败");
        }

        JSONObject jsonObject = jsonArray.getJSONObject(0);

        JSONArray districtsArray = jsonObject.getJSONArray("districts");

        if (districtsArray.size() == 0) {
            throw new MyException(Constants.CODE_HANDEL_FAILED, "业务操作失败");
        }

        return districtsArray;
    }

    /**
     * 逆地理编码
     *
     * @param lon 经度
     * @param lat 纬度
     * @return
     */
    public Map<String, Object> regeo(String lon, String lat) {
        String location = lon + "," + lat;
        // 调用高德地图 将地址转换为经纬度province
        String gaodeJson = restTemplate.getForObject(
                "https://restapi.amap.com/v3/geocode/regeo?key=e4dff7935045e4aadf06e230816b9fcc&location="
                        + location, String.class);


        return JSON.parseObject(gaodeJson, new TypeReference<Map<String, Object>>() {
        });
    }

    //return  "江苏省"

    public Map<String, Object> regeo(String location) {
        // 调用高德地图 将地址转换为经纬度province
        String gaodeJson = restTemplate.getForObject(
                "https://restapi.amap.com/v3/geocode/regeo?batch=true&key=e4dff7935045e4aadf06e230816b9fcc&location="
                        + location, String.class);
        return JSON.parseObject(gaodeJson, new TypeReference<Map<String, Object>>() {
        });
    }

    /**
     * 逆地理编码 获取地址
     *
     * @param lon 经度
     * @param lat 纬度
     * @return
     */
    public String getAddress(String lon, String lat) {
        Map<String, Object> geoInfoMap = this.regeo(lon, lat);
        if (geoInfoMap != null && geoInfoMap.get("regeocode") != null) {
            Map<String, Object> regeocodeMap = (Map<String, Object>) geoInfoMap.get("regeocode");
            if (regeocodeMap.get("formatted_address") != null && regeocodeMap.get("formatted_address") instanceof String) {
                return regeocodeMap.get("formatted_address").toString();
            }
        }
        return "";
    }

    /**
     * 逆地理编码 获取省市区地理位置
     *
     * @param lon 经度
     * @param lat 纬度
     * @return
     */
    public JSONObject getRegion(String lon, String lat) {
        Map<String, Object> geoInfoMap = this.regeo(lon, lat);
        if (geoInfoMap != null && geoInfoMap.get("regeocode") != null) {
            Map<String, Object> regeocodeMap = (Map<String, Object>) geoInfoMap.get("regeocode");
            if (regeocodeMap.get("addressComponent") != null) {
                return (JSONObject) regeocodeMap.get("addressComponent");
            }
        }
        return null;
    }

    /**
     * 根据地址获取经纬度
     *
     * @param address
     * @param city
     * @return
     * @throws MyException
     */
    public Map<String, String> geo(String address, String city) throws MyException {
        Map<String, String> resultMap = new HashMap<>();
        //调用高德地图 将地址转换为经纬度
        String gaodeJson = restTemplate.getForObject(
                "https://restapi.amap.com/v3/geocode/geo?key=e4dff7935045e4aadf06e230816b9fcc&address="
                        + address + "&city=" + city, String.class);
        //判断是否查询失败
        if (JSONObject.parseObject(gaodeJson).getString("status").equals("0")) {
            throw new MyException(Constants.CODE_HANDEL_FAILED, "业务操作失败");
        }
        JSONArray geocodes = JSONObject.parseObject(gaodeJson).getJSONArray("geocodes");
        if (geocodes.size() == 0) {
            throw new MyException(Constants.CODE_HANDEL_FAILED, "请填写正确的地址");
        }
        JSONObject info = geocodes.getJSONObject(0);
        //取地址经纬度
        String location = info.getString("location");
        resultMap.put("longitude", location.substring(0, location.indexOf(",")));
        resultMap.put("latitude", location.substring(location.indexOf(",") + 1));
        return resultMap;
    }

    /**
     * 根据地址获取经纬度
     *
     * @param address
     * @param city
     * @return
     * @throws MyException
     */
    public Map<String, String> geoNew(String address, String city) throws MyException {
        Map<String, String> resultMap = new HashMap<>();
        //调用高德地图 将地址转换为经纬度
        String gaodeJson = restTemplate.getForObject(
                "https://restapi.amap.com/v3/geocode/geo?key=e4dff7935045e4aadf06e230816b9fcc&address="
                        + address + "&city=" + city, String.class);
        //判断是否查询失败
        if (JSONObject.parseObject(gaodeJson).getString("status").equals("0")) {
            return null;
        }
        JSONArray geocodes = JSONObject.parseObject(gaodeJson).getJSONArray("geocodes");
        if (geocodes.size() == 0) {
            return null;
        }
        JSONObject info = geocodes.getJSONObject(0);
        //取地址经纬度
        String location = info.getString("location");
        resultMap.put("longitude", location.substring(0, location.indexOf(",")));
        resultMap.put("latitude", location.substring(location.indexOf(",") + 1));
        return resultMap;
    }

    /**
     * 调用高德地图 算距离
     *
     * @param origins
     * @param destination
     * @param type
     * @return
     */
    public String getDistanceMap(String origins, String destination, String type) {
        String distanceJson = restTemplate.getForObject(
                "https://restapi.amap.com/v3/distance?key=e4dff7935045e4aadf06e230816b9fcc&origins="
                        + origins + "&destination=" + destination
                        + "&type=" + type, String.class);
        Map distanceMap = JSONObject.parseObject(distanceJson);
        //判断是否查询失败
        if ("0".equals(distanceMap.get("status"))) {
            return "";
        }
        List<Map<String, Object>> results = (List<Map<String, Object>>) distanceMap.get("results");
        return results.get(0).get("distance").toString();
    }

    //创建轨迹终端
    public Map<String,Object> terminalAdd(String name) {
        HttpRequest httpRequest =
                HttpRequest.post(MapApiEnum.TERMINALADD.getTypeString())
                        .body("key="+MapKey.apiKey+"&sid="+SERVICE_ID+"&name="+name)
                        .contentType("application/x-www-form-urlencoded");
        String mapRouteString = httpRequest.send().bodyText();
        return JSON.parseObject(mapRouteString, Map.class);
    }

    //查询轨迹终端
    public Map<String,Object> terminalList(String name) {
        HttpRequest httpRequest =
                HttpRequest.get(MapApiEnum.TERMINALLIST.getTypeString()+
                        "key="+MapKey.apiKey+"&sid="+SERVICE_ID+"&name="+name);
        String mapRouteString = httpRequest.send().bodyText();
        return JSON.parseObject(mapRouteString, Map.class);
    }


    //创建轨迹
    public Map<String,Object> terminalTraceAdd(Integer tid) {
        HttpRequest httpRequest =
                HttpRequest.post(MapApiEnum.TRACEADD.getTypeString()+"?key="+MapKey.apiKey+"&sid="+SERVICE_ID+"&tid="+tid)
                        .contentType("application/x-www-form-urlencoded");
        String mapRouteString = httpRequest.send().bodyText();
        return JSON.parseObject(mapRouteString, Map.class);
    }

    //轨迹点上传
    public Map<String,Object> tracePointAdd(Integer tid,Integer trid,JSONArray points) {
        HttpRequest httpRequest =
                HttpRequest.post(MapApiEnum.TRACEPOINTADD.getTypeString())
                        .body("key="+MapKey.apiKey+"&sid="+SERVICE_ID+
                                "&tid="+tid+"&trid="+trid+"&points="+points)
                        .contentType("application/x-www-form-urlencoded");
        String mapRouteString = httpRequest.send().bodyText();
        return JSON.parseObject(mapRouteString, Map.class);
    }

    //查询轨迹点
    public static Map<String,Object> pointList(Integer trid, Integer tid, Long starttime, Long endtime,Integer page,int mapmatch) {

        String getRequest = "";
        if (mapmatch == 1) {

            getRequest = MapApiEnum.TRACELIST.getTypeString() +
                    "?key=" + MapKey.apiKey + "&sid=" + SERVICE_ID + "&tid=" + tid
                    + "&trid=" + trid+ "&starttime=" + starttime+ "&endtime=" + endtime+"&page="
                    + page+ "&pagesize=999"+"&correction=denoise=1,mapmatch=1,attribute=0,threshold=0,mode=driving";
        }else {

            getRequest = MapApiEnum.TRACELIST.getTypeString() +
                    "?key=" + MapKey.apiKey + "&sid=" + SERVICE_ID + "&tid=" + tid
                    + "&trid=" + trid+ "&starttime=" + starttime+ "&endtime=" + endtime+"&page="
                    + page+ "&pagesize=999"+"&correction=denoise=1,mapmatch=0,attribute=1,threshold=0";
        }

//&correction=denoise=1,mapmatch=0,attribute=0,threshold=0,mode=driving&recoup=1&gap=500
        HttpRequest httpRequest =
                HttpRequest.get(getRequest);
        String mapRouteString = httpRequest.send().bodyText();
        return JSON.parseObject(mapRouteString, Map.class);
    }

    //查询轨迹距离
    public static Map<String,Object> pointListNew(Integer trid, Integer tid, Long starttime, Long endtime,Integer page,int mapmatch) {

        String getRequest = "";
        if (mapmatch == 1) {

            getRequest = MapApiEnum.TRACELIST.getTypeString() +
                    "?key=" + MapKey.apiKey + "&sid=" + SERVICE_ID + "&tid=" + tid
                    + "&trid=" + trid+ "&starttime=" + starttime+ "&endtime=" + endtime+"&page="
                    + page+ "&pagesize=999&ispoints=0"+"&correction=denoise=1,mapmatch=1,attribute=0,threshold=0,mode=driving";
        }else {

            getRequest = MapApiEnum.TRACELIST.getTypeString() +
                    "?key=" + MapKey.apiKey + "&sid=" + SERVICE_ID + "&tid=" + tid
                    + "&trid=" + trid+ "&starttime=" + starttime+ "&endtime=" + endtime+"&page="
                    + page+ "&pagesize=999&ispoints=0"+"&mapmatch="+mapmatch;
        }

//&correction=denoise=1,mapmatch=0,attribute=0,threshold=0,mode=driving&recoup=1&gap=500
        HttpRequest httpRequest =
                HttpRequest.get(getRequest);
        String mapRouteString = httpRequest.send().bodyText();
        return JSON.parseObject(mapRouteString, Map.class);
    }

    // 经纬度的转换
    public static Map<String,Object> gaodeConvertGPS(Double GPSlongitude, Double GPSlatitude) {
        String getRequest = MapApiEnum.GAODECONVERTGPS.getTypeString() +
                "?key=" + MapKey.apiKey + "&coordsys=gps" + "&locations=" + GPSlongitude + "," + GPSlatitude;

        HttpRequest httpRequest =
                HttpRequest.get(getRequest);
        String mapRouteString = httpRequest.send().bodyText();
        return JSON.parseObject(mapRouteString, Map.class);
    }

    // 查询经纬度
    public static Map<String,Object> getGPS(String address) {
        String getRequest = MapApiEnum.SELECTPOINT.getTypeString() +
                "?key=" + MapKey.apiKey + "&address=" + address;
        HttpRequest httpRequest =
                HttpRequest.get(getRequest);
        String mapRouteString = httpRequest.send().bodyText();
        return JSON.parseObject(mapRouteString, Map.class);
    }

}

